<template>
  <div class="schema-attr-form">
    <el-form ref="myform" :key="bizdefId" v-loading="requestLoading" :rules="rules" :model="formItem" label-width="160px" size="mini">
      <el-form-item label="模型名称" prop="name">
        <el-input v-model="formItem.name" />
      </el-form-item>
      <el-form-item label="唯一标识" prop="code">
        <el-input v-model="formItem.code" />
      </el-form-item>
      <el-form-item label="描述" prop="desc">
        <el-input v-model="formItem.desc" />
      </el-form-item>
      <el-form-item v-for="(attr, index) in formItem.attrs" :key="attr._dirty" :label="attr.name">
        <dynamic-attr-form v-model="formItem.attrs[index]" pure-tree-type="bizdef" :show-batch-btn="true" @delete="onRemoveAttr(formItem.attrs[index])" @batch-update="onBatchUpdateAttr" />
      </el-form-item>
      <el-form-item>
        <el-button type="text" icon="el-icon-plus" @click="onAddAttr">添加属性</el-button>
        <el-button type="primary" style="margin-right: 20px;" @click="onSave">保存</el-button>
      </el-form-item>
    </el-form>
  </div>

</template>

<script>
import { update, detail, uploadIcon } from '@neu/cmdb-ui/api/bizdef'
import { batchUpdateOneAttr } from '@neu/cmdb-ui/api/bizs'
import { deepClone, createUniqueString } from '@neu/biz-core/utils'
import { getToken } from '@neu/biz-core/utils/auth'
import ValidatorSchema from 'async-validator'
import DynamicAttrForm from '@neu/cmdb-ui/components/DynamicAttrForm'

// 定义一个表单原始项
const formItem = {
  code: '',
  name: '',
  attrs: [],
  desc: '',
  icon: ''
}

// 表单验证规则
const rules = {
  name: [{
    required: true,
    message: '名称必填项',
    trigger: 'blur'
  }],
  code: [{
    required: true,
    message: '编码必填项',
    trigger: 'blur'
  }]
}

export default {
  name: 'BizDefAttrForm',
  components: {
    DynamicAttrForm
  },
  props: {
    bizdefId: {
      required: true,
      type: String
    }
  },
  data() {
    return {
      requestLoading: false,
      formItem: { ...formItem },
      schemaCategories: [],
      activeName: 'first',
      uploadIconUrl: uploadIcon(this.$route.params.id),
      rules: { ...rules },
      descriptor: {} // 动态属性表单验证
    }
  },
  computed: {
    uploadHeaders: function() {
      return {
        'Authentication': getToken()
      }
    }
  },
  created() {
    this.$store.dispatch('cmdb/loadDatatypes')
    this.$store.dispatch('cmdb/loadRelationtypes')
    this.fetch()
  },
  methods: {
    // 初始化表单数据
    fetch() {
      this.requestLoading = true
      detail(this.bizdefId).then(response => {
        console.log(response)
        const { _id, code, name, attrs, desc, icon } = response.data
        let mAttrs = []
        if (attrs) {
          const selfAttrs = attrs.map(a => { a._dirty = createUniqueString(); a._inherit = false; a._error = { name: false, field: false, dtype: false }; return a })
          mAttrs = [...selfAttrs]
        }
        this.formItem = { _id, code, name, attrs: mAttrs, desc, icon }
        this.requestLoading = false
      })
    },

    // 添加一个属性
    onAddAttr() {
      if (this.formItem.attrs.some(a => a.field === '')) return
      this.formItem.attrs.push({
        _dirty: createUniqueString(),
        _error: { name: false, field: false, dtype: false },
        _inherit: false,
        name: '',
        field: '',
        dtype: '',
        len: 255,
        dvalue: '',
        notnullable: false,
        enums: [],
        datasource: {}
      })
    },

    // 删除一个属性
    onRemoveAttr(attr) {
      const idx = this.formItem.attrs.findIndex(a => a.field === attr.field)
      this.formItem.attrs.splice(idx, 1)
    },

    // 批量更新实例属性
    onBatchUpdateAttr(val) {
      batchUpdateOneAttr(this.bizdefId, val.field, val.value).then(response => {
        this.$message({
          type: 'success',
          message: '更新 ' + response.data.nModified + ' 条.'
        })
      })
    },

    // 提交属性表单
    onSave() {
      const that = this
      this.$refs.myform.validate((valid) => {
        if (!valid) return

        this.descriptor['attrs'] = {
          type: 'array',
          fields: {}
        }
        this.formItem.attrs.forEach(attr => {
          if (attr.dtype !== 'datasource') {
            delete attr.datasource
          }
          if (attr.dtype !== 'enum') {
            delete attr.enum
          }
        })
        this.formItem.attrs.forEach((attr, idx) => {
          attr._error = { name: false, field: false, dtype: false }
          const attrRule = {
            type: 'object',
            required: true,
            fields: {
              name: [{
                type: 'string',
                required: true
              }, {
                validator: (rule, value, callback) => {
                  let count = 0
                  this.formItem.attrs.forEach(it => {
                    if (value && it.name === value) count++
                  })
                  if (count > 1) {
                    callback('属性名不能重复')
                  } else {
                    callback()
                  }
                }
              }],
              field: [{
                type: 'string',
                required: true
              }, {
                validator: (rule, value, callback) => {
                  let count = 0
                  this.formItem.attrs.forEach(it => {
                    if (value && it.field === value) count++
                  })
                  if (count > 1) {
                    callback('属性标识不能重复')
                  } else {
                    if (value === 'code' || value === 'name') {
                      callback('code和name是保留关键字')
                    } else {
                      callback()
                    }
                  }
                }
              }],
              dtype: { type: 'string', required: true }
            }
          }
          this.descriptor['attrs'].fields[idx] = attrRule
        })
        var validator = new ValidatorSchema(this.descriptor)

        validator.validate(this.formItem, (errors, fields) => {
          if (errors) {
            errors.forEach(error => {
              const parts = error.field.split('.')
              const attrIndex = parts[1]
              const fieldName = parts[2]
              that.formItem.attrs[attrIndex]._error[fieldName] = true
            })
            return
          }

          this.requestLoading = true
          const { code, name, attrs, desc } = this.formItem
          // const mAttrs = attrs.filter(it => it._inherit !== true)
          const mAttrs = deepClone(attrs.filter(it => it._inherit !== true)).map(it => { delete it._dirty; delete it._error; delete it._inherit; return it })
          const data = { code, name, attrs: mAttrs, desc }
          update(this.bizdefId, data).then(response => {
            this.$message({
              type: 'success',
              message: '保存成功!'
            })
            this.requestLoading = false
          })
        })
      })
    }
  }
}
</script>

<style scoped>
 .schema-attr-form {
   min-height: calc(100vh - 188px);
 }
</style>
